package org.atlantis.grosbeak.depot.proxy;

import java.util.Collection;
import java.util.Map;

import org.atlantis.grosbeak.depot.DepotMaker;
import org.atlantis.grosbeak.depot.desc.ObjectDesc;
import org.atlantis.grosbeak.depot.desc.ValueDesc;
import org.atlantis.grosbeak.depot.proxy.value.ArrayValueProxy;
import org.atlantis.grosbeak.depot.proxy.value.CollectionValueProxy;
import org.atlantis.grosbeak.depot.proxy.value.DepotValueProxy;
import org.atlantis.grosbeak.depot.proxy.value.EnvValueProxy;
import org.atlantis.grosbeak.depot.proxy.value.FileValueProxy;
import org.atlantis.grosbeak.depot.proxy.value.InnerValueProxy;
import org.atlantis.grosbeak.depot.proxy.value.MapValueProxy;
import org.atlantis.grosbeak.depot.proxy.value.ObjectIdValueProxy;
import org.atlantis.grosbeak.depot.proxy.value.ReferValueProxy;
import org.atlantis.grosbeak.depot.proxy.value.StaticValueProxy;

/**
 * 默认的值代理生成器。它会根据值描述（ValueDesc）来决定生成各种实现的值代理。
 * 
 * @author <a href="mailto:seenoevil.cn@gmail.com">SeeNoEvil</a>
 * 
 */
public class DefaultValueProxyMaker implements ValueProxyMaker {

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.atlantis.grosbeak.depot.proxy.ValueProxyMaker#make(org.atlantis.grosbeak
	 * .depot.DepotMaker, org.atlantis.grosbeak.depot.desc.ValueDesc)
	 */
	@SuppressWarnings("unchecked")
	public ValueProxy make(DepotMaker maker, ValueDesc vd) {
		Object value = vd.getValue();
		String type = vd.getType();

		// 处理type为null的情况
		if ("null".equals(type) || null == value) {
			return new StaticValueProxy(null);
		}

		// 处理type为normal的情况
		else if ("normal".equals(type) || null == type) {
			if (value.getClass().isArray()) {
				return new ArrayValueProxy(maker, (ValueDesc[]) value);
			} else if (value instanceof Map<?, ?>) {
				return new MapValueProxy(maker, (Map<String, ValueDesc>) value,
						(Class<? extends Map<String, Object>>) value.getClass());
			} else if (value instanceof Collection<?>) {
				return new CollectionValueProxy(maker,
						(Collection<ValueDesc>) value,
						(Class<? extends Collection<Object>>) value.getClass());
			} else if (value instanceof ObjectDesc) {
				return new InnerValueProxy((ObjectDesc) value);
			}
			return new StaticValueProxy(value);
		}

		// 处理type为连接其他对象的情况
		else if ("refer".equals(type)) {
			String s = value.toString();
			if ("$depot".equalsIgnoreCase(s)) {
				return new DepotValueProxy();
			} else if ("$id".equalsIgnoreCase(s)) {
				return new ObjectIdValueProxy();
			}
			return new ReferValueProxy(s);
		}

		// 处理type为file的情况
		else if ("file".equals(type)) {
			return new FileValueProxy(value.toString());
		}

		// 处理type为env的情况
		else if ("env".equals(type)) {
			return new EnvValueProxy(value.toString());
		}

		// 处理type为inner的情况
		else if ("inner".equals(type)) {
			return new InnerValueProxy((ObjectDesc) value);
		}
		return null;
	}
}
